<?php


/**
 * Greendizer invoice model
 *
 * @author      Youssef El Bied <youssef@greendizer.com>
 */
class Greendizer_Module_Model_Invoice extends Mage_Sales_Model_Order_Invoice
{
    /**
     * Cancel invoice action.
     *
     * @return Mage_Sales_Model_Order_Invoice
     */
    public function cancel()
    {
        parent::cancel();

        if ($this->isSentToGreendizer())
        {
            $this->cancelInGreendizer();
        }

        return $this;
    }

    /**
     * Cancels the invoice in Greendizer.
     */
    protected function cancelInGreendizer()
    {
        try
        {
            set_include_path(sprintf("%s%s%s%slib%sgreendizer-php%sLibrary",
                get_include_path(),
                PATH_SEPARATOR,
                Mage::getModuleDir('', 'Greendizer_Module'),
                DIRECTORY_SEPARATOR,
                DIRECTORY_SEPARATOR,
                DIRECTORY_SEPARATOR
            ));

            require_once 'Greendizer/SellerClient.php';

            $client = new Greendizer_SellerClient(
                array(
                    'email'		=> Mage::getStoreConfig('greendizer_configuration/authentication/email'),
                    'password'	=> Mage::getStoreConfig('greendizer_configuration/authentication/password')
                )
            );
            $collection = $client->getUser()->emails()->getById(Mage::getStoreConfig('greendizer_configuration/authentication/email'))->invoices()->search('customId=='.$this->getIncrementId());
            foreach ($collection->getResources() as $resource)
            {
                $resource->cancel();
                $resource->save();
                break;
            }
        }
        catch (Exception $e)
        {
            Mage::log(sprintf("%s: could not be canceled in Greendizer.", $this->getIncrementId()), Zend_Log::WARN);
            Mage::log($e->getMessage(), Zend_Log::DEBUG);
        }
    }

    /**
     * Returns true if the current invoice has been already sent to Greendizer, false otherwise.
     *
     * @ return True if the current invoice has been already sent to Greendizer, false otherwise.
     */
    public function isSentToGreendizer()
    {
        $value = $this->getSentToGreendizer();
        return $value && $value == 1;
    }

    /**
     * Overrides parent method to add Greendizer sent flag management.
     * @see Mage_Core_Model_Abstract::save()
     */
    public function save()
    {
        parent::save();

        if ($this->isGreendizerSendingActivated() && !$this->isSentToGreendizer() && $this->sendToGreendizer())
        {
            $this->setSentToGreendizer(true);
            parent::save();
        }

        return $this;
    }

    /**
     * Serializes the current Magento invoice into a Greendizer one and sends it.
     *
     * @return True if sending succeded, false otherwise.
     */
    protected function sendToGreendizer()
    {
        try
        {
            set_include_path(sprintf("%s%s%s%slib%sgreendizer-php%sLibrary",
                get_include_path(),
                PATH_SEPARATOR,
                Mage::getModuleDir('', 'Greendizer_Module'),
                DIRECTORY_SEPARATOR,
                DIRECTORY_SEPARATOR,
                DIRECTORY_SEPARATOR
            ));

            require_once 'Greendizer/SellerClient.php';
            require_once 'Greendizer/XMLi/XMLiBuilder.php';
            require_once 'Greendizer/XMLi/Invoice.php';
            require_once 'Greendizer/XMLi/Group.php';
            require_once 'Greendizer/XMLi/Line.php';
            require_once 'Greendizer/XMLi/Discount.php';
            require_once 'Greendizer/XMLi/Tax.php';
            require_once 'Greendizer/XMLi/RateType.php';
            require_once 'Greendizer/XMLi/XMLiNamespace.php';

            $builder = new Greendizer_XMLi_XMLiBuilder();

            $invoice = new Greendizer_XMLi_Invoice();
            $invoice->setName('#'.$this->getIncrementId());
            $invoice->setDescription("Sent with Greendizer Magento Module");
            $invoice->setCustomId($this->getIncrementId());
            $invoice->setStatus(Greendizer_XMLi_InvoiceStatus::PAID);
            $invoice->setCurrency($this->getOrderCurrencyCode());
            $invoice->setDate(date('Y-m-d'));
            $invoice->setDueDate(date('Y-m-d'));

            $namespace = new Greendizer_XMLi_XMLiNamespace('Magento', 'http://www.magentocommerce.com/');
            $invoice->setCustomElement($namespace, 'orderId', $this->getOrderIncrementId());

            $billing_address = $this->getBillingAddress();

            $invoice->getBuyer()->setName($billing_address->getName().($this->isArgumentEmpty($billing_address->getCompany()) ? "" : sprintf(" [%s]", $billing_address->getCompany())));
            $invoice->getBuyer()->setEmail($billing_address->getEmail());

            $invoice->getBuyer()->getAddress()->setStreetAddress($billing_address->getStreetFull());
            $invoice->getBuyer()->getAddress()->setZipCode($billing_address->getPostcode());
            $invoice->getBuyer()->getAddress()->setCity($billing_address->getCity());
            $invoice->getBuyer()->getAddress()->setCountry($billing_address->getCountry());

            if (!$this->isArgumentEmpty($shipping_address = $this->getShippingAddress()))
            {
            	$shipping = new Greendizer_XMLi_Shipping();
            	
            	$shipping->getRecipient()->setName($shipping_address->getName().($this->isArgumentEmpty($shipping_address->getCompany()) ? "" : sprintf(" [%s]", $shipping_address->getCompany())));
            	$shipping->getRecipient()->setEmail($shipping_address->getEmail());
            
                $shipping->getRecipient()->getAddress()->setStreetAddress($shipping_address->getStreetFull());
                $shipping->getRecipient()->getAddress()->setZipCode($shipping_address->getPostcode());
                $shipping->getRecipient()->getAddress()->setCity($shipping_address->getCity());
                $shipping->getRecipient()->getAddress()->setCountry($shipping_address->getCountry());
                
                $invoice->setShipping($shipping);
            }

            $main_group = new Greendizer_XMLi_Group();
            foreach ($this->getAllItems() as $item)
            {
                $line = new Greendizer_XMLi_Line();

                if (!$this->isArgumentEmpty($datetime = $item->getOrderItem()->getCreatedAt()))
                {
                    $line->setDate(substr($datetime, 0, strpos($datetime, ' ')));
                }
                else
                {
                    $line->setDate(date('Y-m-d'));
                }
                $line->setName($item->getName());
                $line->setDescription($item->getDescription());
                $line->setQuantity($this->isPureInteger($item->getQty()) ? intval($item->getQty()) : $item->getQty());
                $line->setUnitPrice($item->getBasePrice());

                if ($tax_amount = $item->getTaxAmount())
                {
                    $tax = new Greendizer_XMLi_Tax();
                    $tax->setName("Taxes");
                    $tax->setDescription("Taxes total for the row");
                    $tax->setType(Greendizer_XMLi_RateType::FIXED);
                    $tax->setRate($tax_amount);

                    $line->addTax($tax);
                }

                if ($discount_amount = $item->getDiscountAmount())
                {
                    $discount = new Greendizer_XMLi_Discount();
                    $discount->setName("Discounts");
                    $discount->setDescription("Discounts total for the row");
                    $discount->setType(Greendizer_XMLi_RateType::FIXED);
                    $discount->setRate($discount_amount);

                    $line->addDiscount($discount);
                }

                $main_group->addLine($line);
            }
            $invoice->addGroup($main_group);

            if ($shipping_amount = $this->getShippingAmount())
            {
                $shipping_group = new Greendizer_XMLi_Group();
                $shipping = new Greendizer_XMLi_Line();
                $shipping->setDate(date('Y-m-d'));
                $shipping->setName("Shipping");
                $shipping->setDescription("Shipping amount");
                $shipping->setQuantity(1);
                $shipping->setUnitPrice($shipping_amount);
                $shipping_group->addLine($shipping);
                $invoice->addGroup($shipping_group);
            }

            $builder->addInvoice($invoice);

            $client = new Greendizer_SellerClient(
                array(
                    'email'		=> Mage::getStoreConfig('greendizer_configuration/authentication/email'),
                    'password'	=> Mage::getStoreConfig('greendizer_configuration/authentication/password')
                )
            );
            $xmli = $builder->toXMLi();
            Mage::log($xmli, Zend_Log::DEBUG);
            $client->getUser()->emails()->getById(Mage::getStoreConfig('greendizer_configuration/authentication/email'))->invoices()->send($xmli);
        }
        catch (Exception $e)
        {
            Mage::log(sprintf("%s: could not be sent to Greendizer.", $this->getIncrementId()), Zend_Log::WARN);
            Mage::log($e->getMessage(), Zend_Log::DEBUG);

            return false;
        }

        return true;
    }
    
    /**
     * Returns true if Greendizer sending is activated, false otherwise.
     */
    protected function isGreendizerSendingActivated() {
    	return !is_null(Mage::getStoreConfig('greendizer_configuration/authentication/activated')) && Mage::getStoreConfig('greendizer_configuration/authentication/activated') == 1;
    }

    /**
     * Returns true if the given argument is empty, false otherwise.
     * @param mixed $argument Argument to be checked.
     */
    protected function isArgumentEmpty($argument)
    {
        return empty($argument);
    }

    /**
     * Returns true if the given argument is a "pure integer", false otherwise.
     * @param mixed $number Number to be checked.
     */
    protected function isPureInteger($number)
    {
        $parts = explode(".", (string) $number);
        if (count($parts) > 1)
        {
            if ($parts[1] != str_repeat("0", count($parts[1])))
            {
                return false;
            }
        }
        return true;
    }
}
